home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1994
/
MacHack 1994.toast
/
MacHack™94
/
Talks & Papers
/
Timothy Knox
/
yerk 3.66
/
System source
/
Base
< prev
next >
Wrap
Text File
|
1994-06-24
|
13KB
|
472 lines
( base ============================== June 12 84 )
( 6/12/84 NDI Added DISK.SCR to front )
( 8/15/84 CBD Added Select{ indexed case structure )
( 10/03/84 CBD Scon and other stuff )
( 10/08/84 CBD Added .h, .d, etc. )
( 10/12/84 CBD Added class error handling )
( 10/12/84 CBD Converted Variables to Values )
( 12/29/84 cbd Added resource string handling )
( 11/12/85 cdn Fixed nullOSstr; Msg# end with a CR )
( 12/20/85 cdn Made ascii sensitive to case )
( 12/12/85 cdn Corrected rDepth )
( 2/21/86 cdn Changed file rewind to set EOF=0 in (save)
( 6/18/86 cdn Added GetRes )
( 6/26/86 cdn Added token )
( 10/09/86 cdn Modified next, for 2.0 nucleus )
( 8/31/88 rfl changed extend to make it faster AND fixed >uc trap a054)
( 7/10/90 rfl modified getstring to return 0 0 if not found
( 12/24/90 rfl changed the word BE to BI so that $be is valid.
( 6/08/91 rfl 'type now works for upper and lower case
( 12/09/92 rfl added switch to ?rdepth so that proc words don't have a problem if stack is
( moved somewhere else in memory due to context switching
( Actualy ?rdepth word moved to source Class
( 5/01/93 rfl added gestalt
( 5/07/93 rfl added asc>bin and bin>asc
( 5/14/93 rfl modified getstring to not open yerk.rsrc...error message if not found
( 11/29/93 rfl modified patch word to understand colon defs with arguments and :code
( definitions. Note that there is still no forward for :code defs., but
( forward does work for named input parameters and local variables.
( 1/01/94 rfl moved file related words to file source: file-install etc
( 3/10/94 rfl added patchL
Decimal
( Ignore rest-of-line; a comment )
: \ R> Drop ; \ Exits to word that called Interpret
Immediate
\ Display contents of return stack
: trace r0 rp@ (.stack) ;
\ Mac File/Record Interface
4 constant cLen \ length of a CFA
0 constant nullVal
: nullOSstr ' nullVal +base ;
\ ( -- ^wordstring ) retrieve next word from input stream
: @word BL word here ;
Create not ' 0= here 4- !
: 0, 0 , ; \ compile an empty cell
\ ( -- n ) parse a number from the input stream
: @val @word number drop ;
\ state-smart single cfa compiler
: 'c @pfa cfa state IF Compile lit , THEN ; Immediate
\ Leave code address on stack of word in input stream
: 'Code @pfa cfa @ [Compile] Literal ; Immediate
'code quit constant colCode
\ make latest word unfindable
: smudge latest 32 toggle ; Immediate
\ ( -- 4bytestring ) OS type literal; both upper and lowercase
: 'type
pad 4 bl fill tib in + bl enclose (lcWord) here count 4 min
pad swap cmove pad @ [Compile] literal
; Immediate
\ true if error; false if no error
: gestalt ( -- response 0 or negativeErr ) [compile] 'type
state
IF compile (gestalt)
ELSE (gestalt)
THEN ; immediate
\ some Forth83 compatible words
Create >Link ' 4- here 4- ! \ ( cfa -- lfa )
Create Link> ' 4+ here 4- ! \ ( lfa -- cfa )
Create >Body ' 4+ here 4- ! \ ( cfa -- pfa )
Create Body> ' cfa here 4- ! \ ( pfa -- cfa )
: Name> pfa cfa ; \ ( nfa -- cfa )
: >Name 4+ nfa ; \ ( cfa -- nfa )
\ Compile an inline string at addr
: str, c@ 1+ align allot ;
0 variable buf255 252 allot \ buffer for string operations
\ Convert a string to a Str255 at buf leaving its absolute addr
\ ( addr len addr -- abs:str255 )
: >str255 >R dup R c! R 1+ swap cmove R> +base ;
: Str255 buf255 >str255 ;
\ ( b -- )
: Abort" ?Comp Compile (Ab") word" Str, ; Immediate
\ State-smart HEX literal word - $ 30
: $ Base >R hex @val
[Compile] literal R> Put base ; Immediate
: w @val state
IF Compile wLitw w, ELSE makeInt THEN ; Immediate
hex
create extend 2017 w, 48c0 w, 2e80 w, $ 4EEB w, next w,
decimal
\ Define state-smart inline string literal
: (lit") R> count 2dup + align >R ; \ runTime handler
\ ( -- addr len )
: " state
IF Compile (lit") word" str,
ELSE word" buf255 over c@ 1+ cmove
buf255 count
THEN
; Immediate
\ Multiple code field support - see JFAR V1 #1, p.55
\ 10/18/84 CBD Version 1
( #cfas seq# [prefix] -- addr #cfas nuseq# )
: DO..
dup 8 > IF , THEN \ compile pfa of prefix
1- 2dup - 4* w, Here rot rot \ (CODEFIELD)
'code dojmp Here 10 allot 10 cmove \ DODO,
[Compile] ]> ;
\ end a DO.. construct
: ..End Compile ;s [Compile] <[ ; Immediate
\ Get inline code and compile it
: (,code)
R> dup w@ swap 2+ swap
2dup + >R Here swap dup allot cmove ;
\ ( addr len -- ) open resource file for name
: OpenResFile
>R >R word0 R> R> str255
$ a997 trap i->l \ call OpenResFile
-1 = abort" resource file open failed" ;
\ open the yerk system resource file
: openNR " yerk.rsrc" OpenResFile ;
openNR
\ ( -- ascii ) Leave ascii val of next char in stream
: Ascii
tib in + bl enclose (LCword)
here 1+ c@ [Compile] literal
; Immediate
\ ( resID -- addr len) get the string with resource ID
: getString
0 swap makeint $ a9ba trap \ call getString
dup 0= IF ." GetString Failed" type abort THEN
>ptr count ;
\ ( strID -- ) print string and abort
: die
." Error# " dup . ascii : emit
getString type 5 beep abort ;
\ ( nfa -- ) print a name field, filter out garbage
: .name
count $ 5f and dup 16 >
IF 2drop ." ??? "
ELSE type space
THEN ." ::" ;
\ ( b -- ) abort with string whose resID is at IP
: (.rAbort)
w@(IP) swap
IF cr ." In " R> drop R cLen - @ >name .name die
ELSE drop
THEN ;
\ ( b -- ) abort and print resource string if true. use: ?error str#
: ?Error Compile (.rAbort) @val w, ; Immediate
\ ( -- ) print string whose resID is at IP
: (.tStr) w@(IP) getString type ;
\ ( -- ) print string for id# in stream
: type# Compile (.tStr) @val w, ; Immediate
\ ( -- ) print string whose resID is at IP
: (.rStr) w@(IP) ." Msg# " dup . ascii : emit getString type cr ;
\ ( -- ) print " Msg#" & string for id# in stream
: msg# Compile (.rStr) @val w, ; Immediate
\ build a dictionary header without a cfa
: header create -4 allot ;
: Build
?error 169 \ not enough codefields
Compile header Compile (,code)
dup 4* W, 0 DO , LOOP
; Immediate
: CodeFields dup ;
\ ================ Resources ===========
\ ( resID type -- handle ) GetRes support word
: (GetRes) 0 swap rot makeInt $ a9a0 trap ; \ call GetResource
\ ( resID : type -- handle ) Load the resource from the resource file chain
: GetRes
[Compile] 'type
state IF Compile (GetRes)
ELSE (GetRes) THEN
; Immediate
\ Resource support - use: 'type TYPE 1 rsrc sam
1 codefields
\ ( -- ^res ) get the resource into memory
Do.. dup 4+ w@ swap @ (GetRes)
dup 0= ?error 170 \ getResource Failed
>ptr ..End
: rsrc Build swap , w, ..End
\ Force printing in hex or decimal
( n -- )
: .H base >R hex . R> Put base ;
: .D base >R decimal . R> Put base ;
\ ( -- ) Goto threaded code whose addr in next dict cell
: (Jmp) R> @ >R ;
\ Patch pfa at old to exec new
\ takes care of both colon code, local parameters, and code defs
: (patch) \ { pfaOld pfaNew \ colNew -- } \ keep pfaOld and pfaNew on stack and use pick
\ colNew is temporarily put on return stack
dup cfa @ over =
IF dup 3 pick cfa ! \ new word is a code definition, -1
ELSE dup cfa @ ' colp <> >r \ be careful...there may be other ids here
r \ if new word is colon, set old as too
IF colCode ELSE ' colp THEN 3 pick cfa ! \ else store colp def
'c (jmp) 3 pick r not IF 2+ THEN ! \ put (jmp) in right place
r not \ if new word has local parms
IF dup w@ 3 pick w! THEN \ then set number of parms in old
dup r> not \ if new word has local parms
IF 2+ 3 pick 2+ \ then store new pfa into old parm field
ELSE 3 pick \ else put it into normal position
THEN clen + !
THEN 2drop ;
\ Patch a word to a newly defined word
\ Use: Patch oldWord newWord
: Patch @pfa @pfa (patch) ; Immediate
\ patch the named word with the latest definition
: patchL @pfa latest pfa (patch) ; Immediate
\ Forward referencing support
\ ( -- ) declare a new forward reference
: Forward
<Builds 0, 0,
Does> cr msg# 109 cLen -
nfa .name R .h abort ;
: :F @pfa Here [Compile] ]> ;
: ;F (patch) Compile ;s [Compile] <[ ; Immediate
\ define a Value - a multiple-cfa structure that responds to
\ Put, ++ and its default action is a fetch
: Value
Header here 12 allot 'c base
swap 12 cmove , ;
\ a vect responds to Put, Get, and default action is execute
: Vect
Header here 12 allot 'c vModel swap
12 cmove , ;
\ ( -- #cells)
: mDepth m0 mp@ - 4 / ;
: rDepth r0 rp@ - 4 / 2- ; \ 2- accounts for threading of rDepth & rp@
: errBeep 5 beep ;
\ ( ^obj -- )
: .ClassName cfa @ nfa .name ;
\ Error routine for objects prints class name first
\ Only valid inside of a method.
: (classErr")
w@(IP) swap
IF cr msg# 104
copym .className copym .h space die
ELSE drop THEN ;
: classErr" Compile (classerr") @val w, ; Immediate
-39 Constant EOF
\ pseudo-assembler macros
: popD0 $ 201F w, ; Immediate \ MOVE.L (A7)+,D0
: popA0 $ 205F w, ; Immediate \ MOVE.L (A7)+,A0
: pushD0 $ 2F00 w, ; Immediate \ MOVE.L D0,-(A7)
: pushA0 $ 2F08 w, ; Immediate \ MOVE.L A0,-(A7)
: next, $ 4EEB w, next w, ; Immediate
\ Define these code words above the nucleus
\ this allows getMtxt to Find them at run time on a sealed nucleus
Create null next,
Create bye $ a9f4 w,
\ ( abs:addr len -- ) map string to upper case
Create >uc
popD0
popA0
$ a054 w, \ call uprString
next,
\ primitive ascii to binary conversion
hex
create (asc>bin) ( str255 -- n)
2057 w, \ movea.l (sp),a0
3f3c0001 , \ move.w #1,-(sp)
7001 w, \ moveq #1,d0
a9ee w, \ call pack7
2e80 w, \ move.l d0,(sp)
next,
: asc>bin ( addr len -- n) str255 (asc>bin) ;
\ string is put into pad
hex
create bin>asc ( n -- addr len )
201f w, \ move.l (sp)+,d0
207c w, pad , \ movea.l YERK[pad],a0
d1cb w, \ adda.l a3,a0
3f3c0000 , \ move.w #0,-(sp)
a9ee w, \ _numToString
4280 w, \ clr.l d0
1018 w, \ move.b (a0)+,d0
91cb w, \ suba.l a3,a0
2f08 w, \ move.l a0,-(sp)
2f00 w, \ move.l d0,-(sp)
next,
decimal
\ ========== Various utility words needed later
\ Become allows restarting at a given word, assuring that all stacks
\ are empty. This is necessary in menu handlers and other areas
\ that could create indefinite nesting situations.
'c quit Vect becomeCFA
: Bi sp! rp! mp! becomeCfa quit ;
: (be) R> @ put becomeCfa bi ;
\ use: Become newWord - compiles code to Be at runtime
: Become
@pfa cfa State
IF Compile (be) , ELSE put becomeCfa bi THEN
; Immediate
cLen CONSTANT CFALEN
\ stack compiled list of values starting at IP
: (lits)
R> dup w@ 4* swap 2+ swap over +
dup >R swap
DO i@ 4 +LOOP ;
\ ( #lits -- #lits ) Compile header for list of literals if compile state
: ,(lits) state IF 'c (Lits) , dup W, THEN ;
\ state-smart word to compile or stack a list of cfas
\ ( #cfas -- ) pull words from stream and compile cfas
: 'cfas
,(lits) 0
DO @pfa cfa State IF , THEN LOOP
; Immediate
\ ( len -- ) Clear and allocate at here
: Reserve Here over erase allot ;
\ String constant leaves Addr Len at runtime
: Scon
<Builds word" Str,
Does> Count ;
\ ( addr1 len1 addr2 len2 -- b ) String compare
: S=
>R Swap R> Over =
IF (s=) ELSE 2drop drop 0 THEN ;
\ ( adr chr -- adrnext adr len ) Parser
: parse
enclose
4 pick + 2swap >R R + rot R> -
;
\ CASE should be used for non-contiguous values.
\ this is a modified Eaker/Duncan model.
\ ofBr takes branch at IP 1 nest back, and preserves val if
\ branch taken, else it is dropped.
: Case ?Comp csp !Csp 4 ; Immediate
\ ( val tst -- ) ofBr will take branch if 0 is on stack
: (of) over = ofBr ;
\ ( val loTst hiTst -- ) Branch if not within inclusive range
: (rof) rot >R R >= swap R <= And R> swap ofBr ;
: Of 4 ?Pairs Compile (of) Here 0, 5 ; Immediate
: rangeOf 4 ?Pairs Compile (rof) Here 0, 5 ; Immediate
: EndOf 5 ?Pairs Compile Branch Here 0,
swap 2 [Compile] THEN 4 ; Immediate
: EndCase 4 ?Pairs Compile drop
BEGIN sp@ csp = not
WHILE 2 [Compile] THEN
REPEAT Put csp ; Immediate
\ the Select structure should be used when dispatching execution
\ on contiguous indices starting at 0. It is smaller and faster
\ than the equivalent CASE construct.
\ An indexed CASE construct for compact, fast execution
\ Runtime word for indexed case execution
-1 Value CaseIndex
: (Select)
Abs R> @ Dup 4+ >R Swap 1+
4* Over Swap - Swap @ Max @ >R ;
\ Begin an indexed case structure - see Forth Dimensions vII p.51
: Select{
Compile (Select) Here 0, 0 0 Put CaseIndex
[Compile] <[
; Immediate
: Is{
?Exec CaseIndex -
?error 102
CaseIndex 1+ put caseIndex
240 [Compile] ]>
; Immediate
: }End
240 ?Pairs
Compile ;S [Compile] <[ Here
; Immediate
: Default{
[Compile] ]>
; Immediate
: }Select
[Compile] ]> Compile ;S , Here Pushm
BEGIN Dup WHILE , REPEAT Drop
Dup 4+ , Here Swap ! PopM 4- ,
; Immediate
<" Args